/**
 * Agent Query Handler
 * 
 * Handles both streaming and single message input modes
 * Based on Claude Agent SDK documentation:
 * https://docs.claude.com/en/api/agent-sdk/streaming-vs-single-mode
 */

import { query as sdkQuery } from '@anthropic-ai/claude-agent-sdk';
import type { AgentOptions, QueryRequest, QueryResponse, StreamEvent } from '@/types';
import { logger } from '@/utils/logger';
import { config } from '@/utils/config';
import { getSubAgentManager } from '@/subagents';

/**
 * Execute a query in streaming mode
 * 
 * Streaming mode provides:
 * - Real-time feedback as responses are generated
 * - Support for image uploads
 * - Queued messages
 * - Tool integration
 * - Hooks support
 * - Context persistence
 * 
 * @param request - Query request with prompt and options
 * @returns Async generator yielding query responses
 */
export async function* executeStreamingQuery(
  request: QueryRequest
): AsyncGenerator<QueryResponse> {
  const { prompt, options = {} } = request;

  logger.info('Executing streaming query', {
    promptType: typeof prompt,
    model: options.model || config.defaultModel,
  });

  try {
    // Enhanced system prompt for thinking chain visualization
    const enhancedSystemPrompt = options.systemPrompt || `你是 CAgent，一个专业的 AI 助手。

**重要指令**：在回答问题时，请使用 <thinking> 标签展示你的推理过程：

<thinking>
1. **问题分析**：理解用户的需求和问题本质
2. **知识检索**：确定需要哪些知识和信息
3. **方案设计**：制定解决方案和回答策略
4. **步骤规划**：列出具体的回答步骤
5. **风险评估**：考虑潜在问题和边界情况
</thinking>

然后在 <thinking> 标签之外给出清晰、准确的最终答案。

示例：
<thinking>
1. **问题分析**：用户想了解...
2. **知识检索**：需要解释...的概念
3. **方案设计**：先介绍基本原理，再给出示例
4. **步骤规划**：
   - 定义和概念
   - 工作原理
   - 代码示例
   - 优缺点分析
5. **风险评估**：注意避免过于技术化的术语
</thinking>

[你的清晰答案]
`;

    // Prepare sub-agents configuration
    let agents: Record<string, any> | undefined;
    try {
      const subAgentManager = getSubAgentManager();

      // If a specific sub-agent is requested, use only that one
      if (options.subAgentId) {
        const subAgent = subAgentManager.getSubAgent(options.subAgentId);
        if (subAgent) {
          // Create agents config with only the selected sub-agent
          const agentsConfig = subAgentManager.getAgentsConfig();
          agents = {
            [options.subAgentId]: agentsConfig[options.subAgentId]
          };
          logger.info('Using specific sub-agent', { subAgentId: options.subAgentId });
        } else {
          logger.warn('Requested sub-agent not found', { subAgentId: options.subAgentId });
        }
      } else if (options.enableSubAgents !== false) {
        // Use all sub-agents
        agents = subAgentManager.getAgentsConfig();
      }
    } catch (error) {
      // SubAgentManager not initialized yet, skip sub-agents
      agents = undefined;
    }

    // Merge with default options
    const queryOptions: AgentOptions = {
      model: options.model || config.defaultModel,
      systemPrompt: enhancedSystemPrompt,
      maxTurns: options.maxTurns || config.maxTurns,
      includePartialMessages: true, // Enable streaming
      agents, // Add sub-agents configuration
      ...options,
    };

    logger.info('Query options', {
      model: queryOptions.model,
      maxTurns: queryOptions.maxTurns,
      subAgentsEnabled: !!agents,
      subAgentsCount: agents ? Object.keys(agents).length : 0,
    });

    // Execute query with Claude Agent SDK
    const queryResult = sdkQuery({
      prompt,
      options: queryOptions as any,
    });

    // Stream responses
    for await (const message of queryResult) {
      if (message.type === 'stream_event') {
        // Stream event (partial message)
        yield {
          type: 'stream_event',
          event: message.event as StreamEvent,
        };
      } else if (message.type === 'assistant') {
        // Complete assistant message
        yield {
          type: 'assistant',
          content: extractTextContent(message),
        };
      } else if (message.type === 'result') {
        // Final result
        yield {
          type: 'result',
          result: message as any,
        };
      }
      // TODO: Add sub-agent event handling when SDK types are updated
    }

    logger.info('Streaming query completed successfully');
  } catch (error) {
    logger.error('Streaming query failed', error);
    yield {
      type: 'error',
      error: {
        code: 'QUERY_ERROR',
        message: error instanceof Error ? error.message : 'Unknown error',
        details: error,
      },
    };
  }
}

/**
 * Execute a query in single message mode
 * 
 * Single message mode is simpler but more limited:
 * - One-shot queries
 * - No image attachments
 * - No dynamic message queueing
 * - No real-time interruption
 * - No hook integration
 * 
 * Use when:
 * - You need a one-shot response
 * - You don't need image attachments, hooks, etc.
 * - You need to operate in a stateless environment (e.g., lambda)
 * 
 * @param request - Query request with prompt and options
 * @returns Query response
 */
export async function executeSingleQuery(
  request: QueryRequest
): Promise<QueryResponse> {
  const { prompt, options = {} } = request;

  logger.info('Executing single query', {
    promptType: typeof prompt,
    model: options.model || config.defaultModel,
  });

  try {
    // Prepare sub-agents configuration
    let agents: Record<string, any> | undefined;
    try {
      const subAgentManager = getSubAgentManager();

      // If a specific sub-agent is requested, use only that one
      if (options.subAgentId) {
        const subAgent = subAgentManager.getSubAgent(options.subAgentId);
        if (subAgent) {
          // Create agents config with only the selected sub-agent
          const agentsConfig = subAgentManager.getAgentsConfig();
          agents = {
            [options.subAgentId]: agentsConfig[options.subAgentId]
          };
          logger.info('Using specific sub-agent', { subAgentId: options.subAgentId });
        } else {
          logger.warn('Requested sub-agent not found', { subAgentId: options.subAgentId });
        }
      } else if (options.enableSubAgents !== false) {
        // Use all sub-agents
        agents = subAgentManager.getAgentsConfig();
      }
    } catch (error) {
      // SubAgentManager not initialized yet, skip sub-agents
      agents = undefined;
    }

    // Merge with default options
    const queryOptions: AgentOptions = {
      model: options.model || config.defaultModel,
      maxTurns: options.maxTurns || 1, // Single turn for one-shot queries
      includePartialMessages: false, // Disable streaming
      agents, // Add sub-agents configuration
      ...options,
    };

    logger.info('Single query options', {
      model: queryOptions.model,
      subAgentsEnabled: !!agents,
      subAgentsCount: agents ? Object.keys(agents).length : 0,
    });

    // Execute query with Claude Agent SDK
    const queryResult = sdkQuery({
      prompt,
      options: queryOptions as any,
    });

    // Collect all messages
    let finalResponse: QueryResponse = {
      type: 'result',
    };

    for await (const message of queryResult) {
      if (message.type === 'assistant') {
        finalResponse = {
          type: 'assistant',
          content: extractTextContent(message),
        };
      } else if (message.type === 'result') {
        finalResponse = {
          type: 'result',
          result: message as any,
        };
      }
    }

    logger.info('Single query completed successfully');
    return finalResponse;
  } catch (error) {
    logger.error('Single query failed', error);
    return {
      type: 'error',
      error: {
        code: 'QUERY_ERROR',
        message: error instanceof Error ? error.message : 'Unknown error',
        details: error,
      },
    };
  }
}

/**
 * Execute a query with automatic mode detection
 * 
 * Automatically chooses between streaming and single mode based on options
 * 
 * @param request - Query request
 * @returns Async generator for streaming mode, or Promise for single mode
 */
export function executeQuery(
  request: QueryRequest
): AsyncGenerator<QueryResponse> | Promise<QueryResponse> {
  const isStreaming = request.options?.includePartialMessages !== false;

  if (isStreaming) {
    return executeStreamingQuery(request);
  } else {
    return executeSingleQuery(request);
  }
}

/**
 * Extract text content from a message
 * 
 * @param message - SDK message
 * @returns Extracted text content
 */
function extractTextContent(message: any): string {
  if (typeof message.content === 'string') {
    return message.content;
  }

  if (Array.isArray(message.content)) {
    return message.content
      .filter((block: any) => block.type === 'text')
      .map((block: any) => block.text)
      .join('');
  }

  return '';
}

/**
 * Resume a previous session
 * 
 * @param sessionId - Session ID to resume
 * @param prompt - New prompt to continue the conversation
 * @param options - Additional options
 * @returns Async generator yielding query responses
 */
export async function* resumeSession(
  sessionId: string,
  prompt: string,
  options: AgentOptions = {}
): AsyncGenerator<QueryResponse> {
  logger.info('Resuming session', { sessionId });

  yield* executeStreamingQuery({
    prompt,
    options: {
      ...options,
      resume: sessionId,
      continue: true,
    },
  });
}

